package de.saar.penguin.give2modelviewer;

import com.jme.app.SimpleGame;
import com.jme.light.DirectionalLight;
import com.jme.light.Light;
import com.jme.light.LightNode;
import com.jme.light.PointLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.util.export.Savable;
import com.jme.util.export.binary.BinaryExporter;
import com.jme.util.export.binary.BinaryImporter;
import com.jme.util.resource.ResourceLocatorTool;
import com.jme.util.resource.SimpleResourceLocator;
import com.jmex.model.converters.*;
import give.client.client3d.JmeUtil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * A class for loading 3D models in various formats. The program will load the model,
 * display it in a jME window, and compile it to a JME model file. Right now, the program
 * is a bit inconvenient to use because it is restricted to loading the models and textures
 * from the directory media/models in the classpath, e.g. within the same Jar file.
 * This should be fixed in the future.
 */
public class App extends SimpleGame {
    private String filename;
    private String modelname;
    private LightNode lightNode;
    private static final String modelpath="media/models/";

    public static void main(String[] args) {
        if (args.length < 1) {
            System.err.println("Usage: give2-modelviewer <objectfilename>");
//            System.err.println("Supported model types: JME, OBJ");
            System.exit(1);
        }

        App x = new App(args[0]);

        if (args.length >= 2) {
            x.setModelName(args[1]);
        }

        x.start();
    }

    public App(String filename) {
        this.filename = filename;
        modelname = null;
    }

    public void setModelName(String modelname) {
        this.modelname = modelname;
    }


    protected void simpleInitGame() {
        DirectionalLight l1 = new DirectionalLight();
        l1.setAmbient(ColorRGBA.white);
        l1.setDiffuse(ColorRGBA.white);
        l1.setDirection(Vector3f.UNIT_XYZ);
        l1.setEnabled(true);
        lightState.attach(l1);

        Light l2 = new PointLight();
        l2.setAmbient(ColorRGBA.white);
        l2.setDiffuse(ColorRGBA.white);
        l2.setEnabled(true);
        lightState.attach(l2);

        lightNode = new LightNode("Light Node");
        lightNode.setLight(l2);

        rootNode.attachChild(lightNode);
        rootNode.setRenderState(lightState);


        try {
            ResourceLocatorTool.addResourceLocator(
                    ResourceLocatorTool.TYPE_TEXTURE,
                    new SimpleResourceLocator(getClass().getClassLoader().getResource(modelpath)));
            ResourceLocatorTool.addResourceLocator(
                    ResourceLocatorTool.TYPE_MODEL,
                    new SimpleResourceLocator(getClass().getClassLoader().getResource(modelpath)));
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }


        try {
//            File file = new File(filename);
            Spatial model = loadModel(filename);

            rootNode.attachChild(model);
        } catch (Exception ex) {
            System.err.println("Couldn't load model " + filename + ": " + ex.toString());
            ex.printStackTrace(System.err);
            System.exit(1);
        }
    }

    private Spatial loadModel (String modelFile){
        Spatial loadedModel = null;
        FormatConverter formatConverter = null;     
        ByteArrayOutputStream BO = new ByteArrayOutputStream();
        String modelFormat = modelFile.substring(modelFile.lastIndexOf(".") + 1, modelFile.length());
        String modelBinary = modelFile.substring(0, modelFile.lastIndexOf(".") + 1) + "jme";
        // use resourcelocator to get the model url
        URL modelURL = ResourceLocatorTool.locateResource(ResourceLocatorTool.TYPE_MODEL, modelBinary);

        System.out.println("@@@@@ " + modelFile + " - " + modelURL);

        //verify the presence of the jbin model
        if (modelURL == null){
            modelURL = ResourceLocatorTool.locateResource(ResourceLocatorTool.TYPE_MODEL, modelFile);
            //evaluate the format
            if (modelFormat.equals("3ds")){
                formatConverter = new MaxToJme();
            } else if (modelFormat.equals("md2")){
                formatConverter = new Md2ToJme();
            } else if (modelFormat.equals("md3")){
                formatConverter = new Md3ToJme();
            } else if (modelFormat.equals("ms3d")){
                formatConverter = new MilkToJme();
            } else if (modelFormat.equals("ase")){
                formatConverter = new AseToJme();
            } else if (modelFormat.equals("obj")){
                formatConverter = new ObjToJme();
            }
            formatConverter.setProperty("mtllib", modelURL);

            try {
                System.out.println("*****");
                formatConverter.convert(modelURL.openStream(), BO);
                loadedModel = (Spatial) BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
                //save the jbin format
                System.out.println("Saving " + modelBinary);
                BinaryExporter.getInstance().save((Savable)loadedModel, new File(modelBinary));
                System.out.println("saved");
            }
            catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        else {
            try {
                //load the jbin format
                loadedModel = (Node) BinaryImporter.getInstance().load(modelURL.openStream());
            }
            catch (IOException e) {
                return null;
            }
        }

        return loadedModel;
    }


    protected void simpleUpdate() {
        lightNode.setLocalTranslation(cam.getLocation());
        super.simpleUpdate();
    }


}
